# Copyright (C) 2006-2008 by Sergio Pistone
# sergio_pistone@yahoo.com.ar
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

require "gtk2"
require "date"
require File.expand_path( File.dirname( __FILE__ ) + "/../i18n/i18n" )

Gtk.init()

module GTK

	def GTK.empty_string?( text )
		return text ? (text.empty? ? true : text.strip().empty? ) : true
	end

	begin
		require "gtksourceview1"
		class TextView < Gtk::SourceView
# 			def initialize( *args )
# 				super( *args )
# 				show_line_markers = false
# 				show_line_numbers = false
# 			end
		end
		class TextBuffer < Gtk::SourceBuffer
		end
	rescue LoadError => e
		class TextView < Gtk::TextView
		end
		class TextBuffer < Gtk::TextBuffer
		end
	end

	class BaseDialog < Gtk::Window

		attr_reader :accepted
		attr_reader :values

		def initialize( values, close_on_escape=true )
			super()
			@values = values
			set_window_position( Gtk::Window::POS_CENTER )
			signal_connect( "destroy" ) { Gtk.main_quit() }
			if close_on_escape
				self.signal_connect( "key_press_event" ) do |widget, event|
					destroy() if event.keyval == Gdk::Keyval::GDK_Escape
				end
			end
		end

		def create_action_buttons( mode="right", accept_text=nil, cancel_text=nil )
			accept_text = GTK.empty_string?( accept_text ) ? I18n.get( "gui.common.accept" ) : accept_text
			cancel_text = GTK.empty_string?( cancel_text ) ? I18n.get( "gui.common.cancel" ) : cancel_text
			@accept_button = Gtk::Button.new( accept_text )
			@cancel_button = Gtk::Button.new( cancel_text )
			@accept_button.signal_connect( "clicked" ) { accept() }
			@cancel_button.signal_connect( "clicked" ) { destroy() }
			if mode == "left"
				hbox = Gtk::HButtonBox.new();
				hbox.layout_style = Gtk::ButtonBox::START
				hbox.add( @accept_button )
				hbox.add( @cancel_button )
			elsif mode == "split"
				hbox = Gtk::HBox.new();
				hbox.pack_start( @accept_button )
				hbox.pack_start( @cancel_button )
			else
				hbox = Gtk::HButtonBox.new();
				hbox.layout_style = Gtk::ButtonBox::END
				hbox.add( @accept_button )
				hbox.add( @cancel_button )
			end
			return hbox
		end
		protected :create_action_buttons

		def exec()
			@accepted = false
			set_modal( true )
			show_all()
		end

		def accept()
			@accepted = true
			destroy()
		end

	end


	class PluginsManagerDialog < BaseDialog

		def initialize( values )
			super( values )

			set_border_width( 5 )
			set_resizable( true )
			set_default_size( 400, 280 )

			set_title( I18n.get( "gui.pluginsmanager.title", @values["script_name"] ) )

			sites_group = Gtk::Frame.new( I18n.get( "gui.pluginsmanager.sites" ) )

			@move_up_button = Gtk::Button.new( I18n.get( "gui.pluginsmanager.sites.moveup" ) )
			@move_down_button = Gtk::Button.new( I18n.get( "gui.pluginsmanager.sites.movedown" ) )

			@used_plugins_store = Gtk::ListStore.new( String )
			@used_plugins_view = Gtk::TreeView.new( @used_plugins_store )
			column = Gtk::TreeViewColumn.new( I18n.get( "gui.pluginsmanager.sites.inuse" ), Gtk::CellRendererText.new(), :text => 0 )
			@used_plugins_view.append_column( column )
			used_plugins_viewport = Gtk::Viewport.new(
				@used_plugins_view.focus_hadjustment(),
				@used_plugins_view.focus_vadjustment()
			)
			used_plugins_viewport.set_shadow_type( Gtk::SHADOW_IN )
			used_plugins_viewport.add( @used_plugins_view )
			used_plugins_scrolledwindow = Gtk::ScrolledWindow.new()
			used_plugins_scrolledwindow.add( used_plugins_viewport )
			@values["used_plugins"].each() do |plugin|
				iter = @used_plugins_store.append()
				@used_plugins_store.set_value( iter, 0, plugin )
			end

			@add_button = Gtk::Button.new( I18n.get( "gui.pluginsmanager.sites.add" ) )
			@remove_button = Gtk::Button.new( I18n.get( "gui.pluginsmanager.sites.remove" ) )

			@unused_plugins_store = Gtk::ListStore.new( String )
			@unused_plugins_view = Gtk::TreeView.new( @unused_plugins_store )
			column = Gtk::TreeViewColumn.new( I18n.get( "gui.pluginsmanager.sites.available" ), Gtk::CellRendererText.new(), :text=>0 )
			@unused_plugins_view.append_column( column )
			unused_plugins_viewport = Gtk::Viewport.new(
				@unused_plugins_view.focus_hadjustment(),
				@unused_plugins_view.focus_vadjustment()
			)
			unused_plugins_viewport.set_shadow_type( Gtk::SHADOW_IN )
			unused_plugins_viewport.add( @unused_plugins_view )
			unused_plugins_scrolledwindow = Gtk::ScrolledWindow.new()
			unused_plugins_scrolledwindow.add( unused_plugins_viewport )
			@values["unused_plugins"].each() do |plugin|
				iter = @unused_plugins_store.append()
				@unused_plugins_store.set_value( iter, 0, plugin )
			end

			misc_group = Gtk::Frame.new( I18n.get( "gui.pluginsmanager.misc" ) )

			@cleanup_lyrics_checkbox = Gtk::CheckButton.new( I18n.get( "gui.pluginsmanager.misc.cleanup" ) )
			@cleanup_lyrics_checkbox.set_active( values["cleanup_lyrics"].to_s() == "true" )

			@single_threaded_checkbox = Gtk::CheckButton.new( I18n.get( "gui.pluginsmanager.misc.singlethreaded" ) )
			@single_threaded_checkbox.set_active( values["single_threaded"].to_s() == "true" )

			@write_log_checkbox = Gtk::CheckButton.new( I18n.get( "gui.pluginsmanager.misc.writelog", "$HOME/.wikilyrics.log" ) )
			@write_log_checkbox.set_active( values["write_log"].to_s() == "true" )

			buttons = create_action_buttons()

			group_grid = Gtk::Table.new( 4, 4, false )
			group_grid.set_row_spacings( 5 )
			group_grid.set_column_spacings( 5 )
			group_grid.attach( @move_up_button, 0, 1, 1, 2, Gtk::FILL, 0 )
			group_grid.attach( @move_down_button, 0, 1, 2, 3, Gtk::FILL, 0 )
			group_grid.attach( used_plugins_scrolledwindow, 1, 2, 0, 4, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND )
			group_grid.attach( @add_button, 2, 3, 1, 2, Gtk::FILL, 0 )
			group_grid.attach( @remove_button, 2, 3, 2, 3, Gtk::FILL, 0 )
			group_grid.attach( unused_plugins_scrolledwindow, 3, 4, 0, 4, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND )
			sites_group.add( group_grid )

			misc_group_vbox = Gtk::VBox.new( false, 0 );
			misc_group_vbox.add( @cleanup_lyrics_checkbox )
			misc_group_vbox.add( @single_threaded_checkbox )
			misc_group_vbox.add( @write_log_checkbox )
			misc_group.add( misc_group_vbox )

			vbox = Gtk::VBox.new( false, 3 );
			vbox.pack_start( sites_group, true )
			vbox.pack_start( misc_group, false )
			vbox.pack_start( buttons, false )

			add( vbox )

			@move_up_button.signal_connect( "clicked" ) { move_up() }
			@move_down_button.signal_connect( "clicked" ) { move_down() }
			@add_button.signal_connect( "clicked" ) { add_plugin() }
			@remove_button.signal_connect( "clicked" ) { remove_plugin() }

			update_accept_button()
		end

		def move_up()
			sel_iter = @used_plugins_view.selection().selected()
			return if sel_iter == nil || sel_iter == @used_plugins_store.iter_first()
			sel_path = sel_iter.path()
			plugin = sel_iter.get_value( 0 )
			@used_plugins_store.remove( sel_iter )
			sel_path.prev!()
			prev_iter = @used_plugins_store.get_iter( sel_path )
			iter = @used_plugins_store.insert_before( prev_iter )
			@used_plugins_store.set_value( iter, 0, plugin )
			@used_plugins_view.selection().select_iter( iter )
		end

		def move_down()
			sel_iter = @used_plugins_view.selection().selected()
			return if sel_iter == nil
			plugin = sel_iter.get_value( 0 )
			sel_path = sel_iter.path()
			return if ! sel_iter.next!()
			next_iter = sel_iter
			iter = @used_plugins_store.insert_after( next_iter )
			@used_plugins_store.set_value( iter, 0, plugin )
			@used_plugins_store.remove( @used_plugins_store.get_iter( sel_path ) )
			@used_plugins_view.selection().select_iter( iter )
		end

		def add_plugin()
			unused_sel_iter = @unused_plugins_view.selection().selected()
			return if unused_sel_iter == nil
			plugin = unused_sel_iter.get_value( 0 )
			@unused_plugins_store.remove( unused_sel_iter )
			iter = @used_plugins_store.append()
			@used_plugins_store.set_value( iter, 0, plugin )
			@used_plugins_view.selection().select_iter( iter )
			update_accept_button()
		end

		def remove_plugin()
			used_sel_iter = @used_plugins_view.selection().selected()
			return if used_sel_iter == nil
			plugin = used_sel_iter.get_value( 0 )
			@used_plugins_store.remove( used_sel_iter )
			iter = @unused_plugins_store.append()
			@unused_plugins_store.set_value( iter, 0, plugin )
			@unused_plugins_view.selection().select_iter( iter )
			update_accept_button()
		end

		def update_accept_button()
			@accept_button.set_sensitive( @used_plugins_store.iter_first() )
		end

		def accept()
			@values = {
				"cleanup_lyrics" => @cleanup_lyrics_checkbox.active?(),
				"single_threaded" => @single_threaded_checkbox.active?(),
				"write_log" => @write_log_checkbox.active?(),
				"used_plugins" => [],
				"script_name" => @values["script_name"],
				"unused_plugins" => []
			}
			iter = @used_plugins_store.iter_first()
			while ( iter )
				@values["used_plugins"].insert( -1, iter.get_value( 0 ) )
				break if ! iter.next!()
			end
			iter = @unused_plugins_store.iter_first()
			while ( iter )
				@values["unused_plugins"].insert( -1, iter.get_value( 0 ) )
				break if ! iter.next!()
			end
			super()
		end

	end


	class WikiPluginDialog < BaseDialog

		def initialize( values )
			super( values )

			set_border_width( 5 )
			set_resizable( true )
			set_default_size( 300, 50 )

			set_title( I18n.get( "gui.wikiplugin.title", values["site_name"] ) )

			general_group = Gtk::Frame.new( I18n.get( "gui.wikiplugin.general" ) )

			@submit_checkbox = Gtk::CheckButton.new( I18n.get( "gui.wikiplugin.general.submit", values["site_name"] ) )
			@submit_checkbox.set_active( values["submit"].to_s() == "true" )

			@review_checkbox = Gtk::CheckButton.new( I18n.get( "gui.wikiplugin.general.review" ) )
			@review_checkbox.set_sensitive( @submit_checkbox.active?() )
			@review_checkbox.set_active( @review_checkbox.sensitive?() && values["review"].to_s() == "true" )

			@prompt_autogen_checkbox = Gtk::CheckButton.new( I18n.get( "gui.wikiplugin.general.autogen" ) )
			@prompt_autogen_checkbox.set_sensitive( @review_checkbox.active?() )
			@prompt_autogen_checkbox.set_active( @prompt_autogen_checkbox.sensitive?() && values["prompt_autogen"].to_s() == "true" )

			@prompt_no_lyrics_checkbox = Gtk::CheckButton.new( I18n.get( "gui.wikiplugin.general.nolyrics" ) )
			@prompt_no_lyrics_checkbox.set_sensitive( @review_checkbox.active?() )
			@prompt_no_lyrics_checkbox.set_active( @prompt_no_lyrics_checkbox.sensitive?() && values["prompt_no_lyrics"].to_s() == "true" )

			login_group = Gtk::Frame.new( I18n.get( "gui.wikiplugin.login" ) )

			username_label = Gtk::Label.new( I18n.get( "gui.wikiplugin.login.username" ) );
			username_label.set_xalign( 0 )
			@username_lineedit = Gtk::Entry.new()
			@username_lineedit.set_text( values["username"] )

			password_label = Gtk::Label.new( I18n.get( "gui.wikiplugin.login.password" ) );
			password_label.set_xalign( 0 )
			@password_lineedit = Gtk::Entry.new()
			@password_lineedit.set_text( values["password"] )
			@password_lineedit.visibility = false

			@username_lineedit.signal_connect( "changed" ) { update_accept_button_state() }
			@submit_checkbox.signal_connect( "toggled" ) { toggle_submit_checked() }
			@review_checkbox.signal_connect( "toggled" ) { toggle_review_checked() }

			buttons = create_action_buttons()
			update_accept_button_state()

			general_grid = Gtk::Table.new( 4, 4, false )
			general_grid.set_row_spacings( 3 )
			general_grid.set_column_spacings( 3 )
			general_grid.attach( @submit_checkbox, 0, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
			general_grid.attach( @review_checkbox, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, 0, 0 )
			general_grid.attach( @prompt_autogen_checkbox, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
			general_grid.attach( @prompt_no_lyrics_checkbox, 0, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
			general_group.add( general_grid )

			login_grid = Gtk::Table.new( 4, 4, false )
			login_grid.set_row_spacings( 3 )
			login_grid.set_column_spacings( 3 )
			login_grid.attach( username_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			login_grid.attach( @username_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
			login_grid.attach( password_label, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			login_grid.attach( @password_lineedit, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
			login_group.add( login_grid )

			vbox = Gtk::VBox.new( false, 3 );
			vbox.add( general_group )
			vbox.add( login_group )
			vbox.pack_start( buttons, false )

			add( vbox )
		end

		def toggle_submit_checked()
			checked = @submit_checkbox.active?()
			@review_checkbox.set_sensitive( checked )
			if ! checked
				@review_checkbox.set_active( false )
				@prompt_autogen_checkbox.set_active( false )
				@prompt_no_lyrics_checkbox.set_active( false )
			end
			update_accept_button_state()
		end

		def toggle_review_checked()
			checked = @review_checkbox.active?()
			@prompt_autogen_checkbox.set_sensitive( checked )
			@prompt_no_lyrics_checkbox.set_sensitive( checked )
			if ! checked
				@prompt_autogen_checkbox.set_active( false )
				@prompt_no_lyrics_checkbox.set_active( false )
			end
		end

		def update_accept_button_state()
			@accept_button.set_sensitive( ! @submit_checkbox.active?() || ! @username_lineedit.text().empty? )
		end

		def accept()
			@values = {
				"submit"			=> @submit_checkbox.active?(),
				"review"			=> @review_checkbox.active?(),
				"prompt_autogen"	=> @prompt_autogen_checkbox.active?(),
				"prompt_no_lyrics"	=> @prompt_no_lyrics_checkbox.active?(),
				"username"			=> @username_lineedit.text(),
				"password"			=> @password_lineedit.text(),
			}
			super()
		end
	end

	class SubmitSongDialog < BaseDialog

		def initialize( values )
			super( values )

			set_border_width( 5 )
			set_resizable( true )
			set_default_size( 600, 400 )
			resize( 600, 400 )

			edit_mode = @values["edit_mode"].to_s() == "true"

			set_title( I18n.get( "gui.submitsong.title." + (edit_mode ? "edit" : "submit"), values["site_name"] ) )

			artist_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.artist" )}</b>" );
			artist_label.set_xalign( 0.9 )
			artist_label.set_use_markup( true )
			@artist_lineedit = Gtk::Entry.new()
			@artist_lineedit.set_text( values["artist"] )

			title_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.song" )}</b>" );
			title_label.set_xalign( 0.9 )
			title_label.set_use_markup( true )
			@title_lineedit = Gtk::Entry.new()
			@title_lineedit.set_text( values["title"] )

			credits_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.credits" )}</b>" );
			credits_label.set_xalign( 0.9 )
			credits_label.set_use_markup( true )
			@credits_lineedit = Gtk::Entry.new()
			@credits_lineedit.set_text( values["credits"] )

			lyricist_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.lyricist" )}</b>" );
			lyricist_label.set_xalign( 0.9 )
			lyricist_label.set_use_markup( true )
			@lyricist_lineedit = Gtk::Entry.new()
			@lyricist_lineedit.set_text( values["lyricist"] )

			year_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.year" )}</b>" );
			year_label.set_xalign( 0.9 )
			year_label.set_use_markup( true )
			@year_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["year"], 1900, Date.today().year, 1, 10, 0 ) )
			@year_spinbox.set_numeric( true )

			album_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.album" )}</b>" );
			album_label.set_xalign( 0.9 )
			album_label.set_use_markup( true )
			@album_lineedit = Gtk::Entry.new()
			@album_lineedit.set_text( values["album"] )

			@instrumental_checkbox = Gtk::CheckButton.new( I18n.get( "gui.submitsong.instrumental" ) )
			@instrumental_checkbox.set_active( values["instrumental"].to_s == "true" )
			@instrumental_checkbox.signal_connect( "toggled" ) { toggle_instrumental_checked() }

			lyrics_scrolled_window = Gtk::ScrolledWindow.new()
			lyrics_scrolled_window.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
			@lyrics_text_buffer = GTK::TextBuffer.new()
			@lyrics_text_buffer.set_text( values["lyrics"] )
			@lyrics_text = GTK::TextView.new()
			@lyrics_text.set_indent( 2 )
			@lyrics_text.set_buffer( @lyrics_text_buffer )
			lyrics_scrolled_window.add( @lyrics_text )
			@lyrics_text.set_sensitive( ! @instrumental_checkbox.active?() )

			@reviewed_checkbox = Gtk::CheckButton.new( I18n.get( "gui.common.reviewed" ) )
			@reviewed_checkbox.set_active( false )

			buttons = create_action_buttons( "split", I18n.get( "gui.common.submit" ) )

			lyrics_frame = Gtk::Frame.new()
			lyrics_frame.add( lyrics_scrolled_window )
			lyrics_frame.set_shadow_type( Gtk::SHADOW_IN )

			grid = Gtk::Table.new( 9, 4, false )
			grid.set_row_spacings( 3 )
			grid.attach( artist_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @artist_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( title_label, 2, 3, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @title_lineedit, 3, 4, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( credits_label, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @credits_lineedit, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( lyricist_label, 2, 3, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @lyricist_lineedit, 3, 4, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( year_label, 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @year_spinbox, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( album_label, 2, 3, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @album_lineedit, 3, 4, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( @instrumental_checkbox, 0, 4, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( lyrics_frame, 0, 4, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL )
			grid.attach( @reviewed_checkbox, 0, 4, 5, 6, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( buttons, 0, 4, 6, 7, Gtk::EXPAND|Gtk::FILL, 0 )

			add( grid )

		end

		def toggle_instrumental_checked()
			@lyrics_text.set_sensitive( ! @instrumental_checkbox.active?() )
		end

		def accept()
			@values = {
				"artist"		=> @artist_lineedit.text(),
				"year"			=> @year_spinbox.value().to_i(),
				"album"			=> @album_lineedit.text(),
				"title"			=> @title_lineedit.text(),
				"lyrics"		=> @lyrics_text_buffer.text(),
				"instrumental"	=> @instrumental_checkbox.active?(),
				"lyricist"		=> @lyricist_lineedit.text(),
				"credits"		=> @credits_lineedit.text(),
				"reviewed"		=> @reviewed_checkbox.active?()
			}
			super()
		end

	end


	class SubmitAlbumDialog < BaseDialog

		def initialize( values )
			super( values )

			set_border_width( 5 )
			set_resizable( true )
			set_default_size( 600, 400 )
			resize( 600, 400 )

			set_title( I18n.get( "gui.submitalbum.title", values["site_name"] ) )

			artist_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.artist" )}</b>" );
			artist_label.set_xalign( 0.9 )
			artist_label.set_use_markup( true )
			@artist_lineedit = Gtk::Entry.new()
			@artist_lineedit.set_text( values["artist"] )

			album_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.album" )}</b>" );
			album_label.set_xalign( 0.9 )
			album_label.set_use_markup( true )
			@album_lineedit = Gtk::Entry.new()
			@album_lineedit.set_text( values["album"] )

			year_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.year" )}</b>" );
			year_label.set_xalign( 0.9 )
			year_label.set_use_markup( true )
			@year_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["year"].to_i(), 1900, Date.today().year, 1, 10, 0 ) )
			@year_spinbox.set_numeric( true )

			month_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.month" )}</b>" );
			month_label.set_xalign( 0.9 )
			month_label.set_use_markup( true )
			@month_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["month"].to_i(), 0, 12, 1, 1, 0 ) )
			@month_spinbox.set_numeric( true )

			day_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.day" )}</b>" );
			day_label.set_xalign( 0.9 )
			day_label.set_use_markup( true )
			@day_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["day"].to_i(), 0, 31, 1, 1, 0 ) )
			@day_spinbox.set_numeric( true )

			image_label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.image" )}</b>" );
			image_label.set_xalign( 0.9 )
			image_label.set_use_markup( true )
			@image_path_lineedit = Gtk::Entry.new()
			if values.include?( "image_path" )
				@image_path_lineedit.set_text( values["image_path"] )
				@image_button = Gtk::Button.new( "..." )
				@image_button.signal_connect( "clicked" ) { browse_image() }
			else
				@image_path_lineedit.set_text( I18n.get( "gui.submitalbum.coverfound" ) )
				@image_path_lineedit.set_sensitive( false )
			end

			tracks_scrolled_window = Gtk::ScrolledWindow.new()
			tracks_scrolled_window.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
			@tracks_text_buffer = GTK::TextBuffer.new()
			@tracks_text_buffer.set_text( values["tracks"] )
			@tracks_text = GTK::TextView.new()
			@tracks_text.set_indent( 2 )
			@tracks_text.set_buffer( @tracks_text_buffer )
			tracks_scrolled_window.add( @tracks_text )

			@reviewed_checkbox = Gtk::CheckButton.new( I18n.get( "gui.common.reviewed" ) )
			@reviewed_checkbox.set_active( false )

			buttons = create_action_buttons( "split", I18n.get( "gui.common.submit" ) )

			image_hbox = Gtk::HBox.new();
			image_hbox.pack_start( @image_path_lineedit, true, true )
			image_hbox.pack_start( @image_button, false, true ) if values.include?( "image_path" )

			tracks_frame = Gtk::Frame.new()
			tracks_frame.add( tracks_scrolled_window )
			tracks_frame.set_shadow_type( Gtk::SHADOW_IN )

			grid = Gtk::Table.new( 9, 4, false )
			grid.set_row_spacings( 3 )
			grid.attach( artist_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @artist_lineedit, 1, 6, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( album_label, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @album_lineedit, 1, 6, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( year_label, 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @year_spinbox, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( month_label, 2, 3, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @month_spinbox, 3, 4, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( day_label, 4, 5, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @day_spinbox, 5, 6, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( image_label, 0, 1, 3, 4, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( image_hbox, 1, 6, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( tracks_frame, 0, 6, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL )
			grid.attach( @reviewed_checkbox, 0, 6, 5, 6, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( buttons, 0, 6, 6, 7, Gtk::EXPAND|Gtk::FILL, 0 )

			add( grid )

		end

		def browse_image()
			dirname = @image_path_lineedit.text().strip()
			dirname = GTK.empty_string?( dirname ) ? (ENV["HOME"] ? ENV["HOME"] : ".") : File.dirname( dirname )
			dialog = Gtk::FileChooserDialog.new(
				I18n.get( "gui.uploadcover.browseimage.title" ), self, Gtk::FileChooser::ACTION_OPEN, nil,
				[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
				[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT]
			)

			filter = Gtk::FileFilter.new()
			filter.set_name( I18n.get( "gui.uploadcover.browseimage.images" ) )
			["jpg", "png", "bmp"].each() { |ext| filter.add_pattern( "*.#{ext}" ).add_pattern( "*.#{ext.upcase}" ) }
			dialog.add_filter( filter )
			filter = Gtk::FileFilter.new()
			filter.set_name( I18n.get( "gui.uploadcover.browseimage.allfiles" ) )
			filter.add_pattern( "*" )
			dialog.add_filter( filter )

			dialog.set_local_only( true )
			dialog.set_select_multiple( false )
			dialog.set_current_folder( File.expand_path( dirname ) )
			if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
        		image_path = GLib.filename_to_utf8( dialog.filename )
				@image_path_lineedit.set_text( image_path.strip() ) if ! GTK.empty_string?( image_path )
			end
			dialog.destroy()
		end

		def accept()
			aux = {
				"artist"	=> @artist_lineedit.text(),
				"album"		=> @album_lineedit.text(),
				"year"		=> @year_spinbox.value().to_i(),
				"month"		=> @month_spinbox.value().to_i(),
				"day"		=> @day_spinbox.value().to_i(),
				"tracks"	=> @tracks_text_buffer.text(),
				"reviewed"	=> @reviewed_checkbox.active?()
			}
			aux["image_path"] = @image_path_lineedit.text() if @values.include?( "image_path" )
			@values = aux
			super()
		end

	end


	class UploadCoverDialog < BaseDialog

		def initialize( values )
			super( values )

			set_border_width( 5 )
			set_resizable( true )
			set_default_size( 350, 100 )
			set_title( I18n.get( "gui.uploadcover.title", values["site_name"] ) )

			album_group = Gtk::Frame.new( I18n.get( "gui.common.album" ) )

			artist_label = Gtk::Label.new( I18n.get( "gui.common.artist" ) )
			artist_label.set_xalign( 0 )
			@artist_lineedit = Gtk::Entry.new()
			@artist_lineedit.set_text( values["artist"] )

			album_label = Gtk::Label.new( I18n.get( "gui.common.album" ) )
			album_label.set_xalign( 0 )
			@album_lineedit = Gtk::Entry.new()
			@album_lineedit.set_text( values["album"] )

			year_label = Gtk::Label.new( I18n.get( "gui.common.year" ) );
			year_label.set_xalign( 0 )
			@year_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["year"], 1900, Date.today().year, 1, 10, 0 ) )
			@year_spinbox.set_numeric( true )

			image_group = Gtk::Frame.new( I18n.get( "gui.common.image" ) )

			image_label = Gtk::Label.new( I18n.get( "gui.uploadcover.imagepath" ) )
			image_label.set_use_markup( true )
			@image_path_lineedit = Gtk::Entry.new()
			@image_path_lineedit.set_text( values["image_path"] )
			@image_button = Gtk::Button.new( "..." )
			@image_button.signal_connect( "clicked" ) { browse_image() }

			buttons = create_action_buttons()

			album_grid = Gtk::Table.new( 4, 4, false )
			album_grid.set_row_spacings( 3 )
			album_grid.set_column_spacings( 3 )
			album_grid.attach( artist_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			album_grid.attach( @artist_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
			album_grid.attach( album_label, 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			album_grid.attach( @album_lineedit, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
			album_grid.attach( year_label, 0, 1, 3, 4, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			album_grid.attach( @year_spinbox, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
			album_group.add( album_grid )

			image_grid = Gtk::Table.new( 4, 4, false )
			image_grid.set_row_spacings( 3 )
			image_grid.set_column_spacings( 3 )
			image_grid.attach( image_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			image_grid.attach( @image_path_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
			image_grid.attach( @image_button, 2, 3, 0, 1, 0, 0 )
			image_group.add( image_grid )

			vbox = Gtk::VBox.new( false, 3 );
			vbox.add( album_group )
			vbox.add( image_group )
			vbox.add( buttons )

			add( vbox )

		end

		def browse_image()
			dirname = @image_path_lineedit.text().strip()
			dirname = GTK.empty_string?( dirname ) ? (ENV["HOME"] ? ENV["HOME"] : ".") : File.dirname( dirname )
			dialog = Gtk::FileChooserDialog.new(
				I18n.get( "gui.uploadcover.browseimage.title" ), self, Gtk::FileChooser::ACTION_OPEN, nil,
				[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
				[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT]
			)

			filter = Gtk::FileFilter.new()
			filter.set_name( I18n.get( "gui.uploadcover.browseimage.images" ) )
			["jpg", "png", "bmp"].each() { |ext| filter.add_pattern( "*.#{ext}" ).add_pattern( "*.#{ext.upcase}" ) }
			dialog.add_filter( filter )
			filter = Gtk::FileFilter.new()
			filter.set_name( I18n.get( "gui.uploadcover.browseimage.allfiles" ) )
			filter.add_pattern( "*" )
			dialog.add_filter( filter )

			dialog.set_local_only( true )
			dialog.set_select_multiple( false )
			dialog.set_current_folder( File.expand_path( dirname ) )
			if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
        		image_path = GLib.filename_to_utf8( dialog.filename )
				@image_path_lineedit.set_text( image_path.strip() ) if ! GTK.empty_string?( image_path )
			end
			dialog.destroy()
		end

		def accept()
			@values = {
				"artist"		=> @artist_lineedit.text(),
				"album"			=> @album_lineedit.text(),
				"year"			=> @year_spinbox.value().to_i(),
				"image_path"	=> @image_path_lineedit.text()
			}
			super()
		end
	end


	class FixPagesDialog < BaseDialog

		def initialize( values )
			super( values )

			@fetch_func = eval( @values["fetch_func"] )
			@fix_func = eval( @values["fix_func"] )
			@submit_func = eval( @values["submit_func"] )

			set_border_width( 5 )
			set_resizable( true )
			set_default_size( 600, 400 )
			resize( 600, 400 )

			set_title( "#{values["site_name"]} - #{values["title"]}" )

			label = Gtk::Label.new( "<b>#{I18n.get( "gui.common.url" )}</b>" );
			label.set_use_markup( true )
			label.set_xalign( 0.9 )
			@url_lineedit = Gtk::Entry.new()
			@url_lineedit.set_text( values["url"] )

			page_scrolled_window = Gtk::ScrolledWindow.new()
			page_scrolled_window.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
			@page_text_buffer = GTK::TextBuffer.new()
			@page_text_buffer.set_text( "" )
			@page_text = GTK::TextView.new()
			@page_text.set_indent( 2 )
			@page_text.set_buffer( @page_text_buffer )
			page_scrolled_window.add( @page_text )
			page_frame = Gtk::Frame.new()
			page_frame.add( page_scrolled_window )
			page_frame.set_shadow_type( Gtk::SHADOW_IN )

			@fetch_button = Gtk::Button.new( I18n.get( "gui.common.load" ) )
			@fix_button = Gtk::Button.new( I18n.get( "gui.common.fix" ) )
			@submit_button = Gtk::Button.new( I18n.get( "gui.common.submit" ) )

			hbox = Gtk::HButtonBox.new();
			hbox.layout_style = Gtk::ButtonBox::END
			hbox.add( @fetch_button )
			hbox.add( @fix_button )
			hbox.add( @submit_button )

			grid = Gtk::Table.new( 3, 2, false )
			grid.set_row_spacings( 3 )
			grid.attach( label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @url_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( page_frame, 0, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::EXPAND|Gtk::FILL )
			grid.attach( hbox, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )

			add( grid )

			@fetch_button.signal_connect( "clicked" ) { fetch_page() }
			@fix_button.signal_connect( "clicked" ) { fix_page() }
			@submit_button.signal_connect( "clicked" ) { submit_page() }
		end

		def fetch_page()
			if (page_content = @fetch_func.call( @url_lineedit.text() ))
				@original_content = page_content
				@original_url = @url_lineedit.text()
				@page_text_buffer.set_text( page_content )
			end
		end

		def fix_page()
			@page_text_buffer.set_text( @fix_func.call( @page_text_buffer.text() ) ) if @original_content
		end

		def submit_page()
			if @original_content && @original_content != (page_content = @page_text_buffer.text())
				if @submit_func.call( @original_url, page_content )
					@original_content = page_content
					puts I18n.get( "gui.fixpages.success", @original_url )
				else
					puts I18n.get( "gui.fixpages.error", @original_url )
				end
			end
		end

	end


	class SearchLyricsDialog < BaseDialog

		def initialize( values )
			super( values )

			set_border_width( 5 )
			set_resizable( true )
			set_default_size( 300, 50 )
			set_title( I18n.get( "gui.searchlyrics.title" ) )

			group = Gtk::Frame.new( I18n.get( "gui.searchlyrics.search" ) )

			artist_label = Gtk::Label.new( I18n.get( "gui.common.artist" ) )
			artist_label.set_xalign( 0 )
			@artist_lineedit = Gtk::Entry.new()
			@artist_lineedit.set_text( values["artist"] )

			title_label = Gtk::Label.new( I18n.get( "gui.common.song" ) )
			title_label.set_xalign( 0 )
			@title_lineedit = Gtk::Entry.new()
			@title_lineedit.set_text( values["title"] )

			album_label = Gtk::Label.new( I18n.get( "gui.common.album" ) );
			album_label.set_xalign( 0 )
			@album_lineedit = Gtk::Entry.new()
			@album_lineedit.set_text( values["album"] )

			year_label = Gtk::Label.new( I18n.get( "gui.common.year" ) );
			year_label.set_xalign( 0 )
			@year_spinbox = Gtk::SpinButton.new( Gtk::Adjustment.new( values["year"], 1900, Date.today().year, 1, 10, 0 ) )
			@year_spinbox.set_numeric( true )

			buttons = create_action_buttons()

			grid = Gtk::Table.new( 4, 4, false )
			grid.set_row_spacings( 3 )
			grid.set_column_spacings( 3 )
			grid.attach( artist_label, 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @artist_lineedit, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( title_label, 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @title_lineedit, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( album_label, 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @album_lineedit, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, 0 )
			grid.attach( year_label, 0, 1, 3, 4, Gtk::SHRINK|Gtk::FILL, 0, 5 )
			grid.attach( @year_spinbox, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, 0 )
			group.add( grid )

			vbox = Gtk::VBox.new( false, 3 );
			vbox.add( group )
			vbox.add( buttons )

			add( vbox )

		end

		def accept()
			@values = {
				"artist"	=> @artist_lineedit.text(),
				"title"		=> @title_lineedit.text(),
				"album"		=> @album_lineedit.text(),
				"year"		=> @year_spinbox.value().to_i(),
			}
			super()
		end
	end


	class ShowLyricsDialog < BaseDialog

		def initialize( values )
			super( values )

			set_border_width( 5 )
			set_resizable( true )
			set_default_size( 400, 400 )
			resize( 350, 400 )

			title = I18n.get( "gui.lyrics.title", @values["title"], @values["artist"] )
			title += " [#{@values["site_name"]}]" if @values["site_name"]
			set_title( title )

			lyrics_scrolled_window = Gtk::ScrolledWindow.new()
			lyrics_scrolled_window.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
			@lyrics_text_buffer = GTK::TextBuffer.new()
			@lyrics_text_buffer.set_text( values["lyrics"] )
			@lyrics_text = GTK::TextView.new()
			@lyrics_text.set_indent( 2 )
			@lyrics_text.set_buffer( @lyrics_text_buffer )
			lyrics_scrolled_window.add( @lyrics_text )

			lyrics_frame = Gtk::Frame.new()
			lyrics_frame.add( lyrics_scrolled_window )
			lyrics_frame.set_shadow_type( Gtk::SHADOW_IN )

			add( lyrics_frame )
		end

	end

end
